module scene.box;

import utils.vector3;
import scene.ray;

struct Box {
    Vector3f[2] p;

    public static Box opCall(Vector3f p1, Vector3f p2) {
        Box res;
        res.p[0] = p1;
        res.p[1] = p2;
        return res;
    }

    /**
     * Ray-box intersection using IEEE numerical properties to ensure that the
     * test is both robust and efficient, as described in:
     *
     *      Amy Williams, Steve Barrus, R. Keith Morley, and Peter Shirley
     *      "An Efficient and Robust Ray-Box Intersection Algorithm"
     *      Journal of graphics tools, 10(1):49-54, 2005
     *
     */
    public bool intersectRay(inout Ray isRay, inout float tmin, inout float tmax) {
        float tymin, tymax, tzmin, tzmax;

        tmin = (p[isRay.sign[0]].x - isRay.start.x) * isRay.invDir.x;
        tmax = (p[1-isRay.sign[0]].x - isRay.start.x) * isRay.invDir.x;
        tymin = (p[isRay.sign[1]].y - isRay.start.y) * isRay.invDir.y;
        tymax = (p[1-isRay.sign[1]].y - isRay.start.y) * isRay.invDir.y;
        if ( (tmin > tymax) || (tymin > tmax) )
            return false;
        if (tymin > tmin)
            tmin = tymin;
        if (tymax < tmax)
            tmax = tymax;
        tzmin = (p[isRay.sign[2]].z - isRay.start.z) * isRay.invDir.z;
        tzmax = (p[1-isRay.sign[2]].z - isRay.start.z) * isRay.invDir.z;
        if ( (tmin > tzmax) || (tzmin > tmax) )
            return false;
        if (tzmin > tmin)
            tmin = tzmin;
        if (tzmax < tmax)
            tmax = tzmax;

        return ((tmin < isRay.tMax) && (tmax > 0.0f));
    }

    ///return maximum extent and set axis to longest axis found
    public uint maxExtent() {
        Vector3f ext = p[1] - p[0];
        //float ret = ext.x1;
        uint axis = 0;
        if (ext.x2 > ext.x1) {
            axis = 1;
            //ret = ext.x2;
        }
        if (ext.x3 > ext.x2) {
            axis = 2;
            //ret = ext.x3;
        }
        //return ret;
        return axis;
    }
}
